/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package plures;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Map;
import util.Pair;

/**
 *
 * @author Guilherme
 */
public class Data implements Serializable, Cloneable
{
    private final int               key;
    private byte[]                  value;
    private Backup        backup;
    private VersionsArray           versions;
    private static int              INIT_VALUE = 1;

    public Data(int key, String value, int client)
    {
        this.key = key;
        this.value = this.fill(value);
        
        this.backup = new Backup(key);
        this.backup.replace(client, this);
        
        this.versions = new VersionsArray();
        this.versions.put(client, INIT_VALUE);
        
    }   
    
    private Data(int key, byte[] value)
    {
        this.key = key;
        this.value = value;
    }
    
    public Data clone()
    {
        Data d = new Data(this.key, this.value);
        d.versions = new VersionsArray(this.versions);
        return d;
    }
    
    public boolean canUpdate(int client)
    {
        Data d = this.backup.getClientBackup(client);
        return d == null ? false : d.versions.compare(this.versions);
    }
    
    public byte[] fill(String value)
    {
        byte[] bytesValue = new byte[Core.VALUE_LENGTH];
        byte[] tmpArray = value.getBytes();
        int length = tmpArray.length < Core.VALUE_LENGTH ? tmpArray.length : Core.VALUE_LENGTH;
        System.arraycopy(tmpArray, 0, bytesValue, 0, length);
        return bytesValue;
    }
    
    public byte[] getValue(int client)
    {
        // se o cliente está vendo o dado pela primeira vez
        if(this.versions.get(client) == null)
        {
            this.versions.put(client, 0);
            
            // se o cliente está vendo uma nova versão
        } 
        this.backup.replace(client, this.clone());
        return value;
    }
    
    public byte[] simpleGetValue(int client)
    {
        return value;
    }

    public void setValue(String value, int client)
    {
        this.value = this.fill(value);
        this.versions.update(client);
        this.backup.replace(client, this.clone());
    }

    public ArrayList<Pair<Integer,Integer>> getVersionsVector()
    {
        ArrayList<Pair<Integer,Integer>> versions = new ArrayList<>();
        for(Map.Entry<Integer,Integer> item : this.versions.entrySet())
        {
            versions.add(new Pair(item.getKey(), item.getValue()));
        }
        return versions;
    }
    
    public boolean clearBackup()
    {
        this.backup.clear();
        return true;
    } 
        
}
